package cn.cai.pethome.system.service.impl;

import cn.cai.pethome.base.PreAuthorize;
import cn.cai.pethome.base.util.Classutil;
import cn.cai.pethome.system.domain.Permission;
import cn.cai.pethome.system.listener.ScanControllerPackage;
import cn.cai.pethome.system.mapper.PermissionMapper;
import cn.cai.pethome.system.service.IPermissionService;
import cn.cai.pethome.base.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xiaocai
 * @since 2022-09-05
 */
@Slf4j
@Service
public class PermissionServiceImpl extends BaseServiceImpl<Permission> implements IPermissionService {


    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private ScanControllerPackage scanControllerPackage;

    /**
     * 扫描所有controller包，解析@PreAuthorize注解，插入权限表数据
     */
    @Override
    public void scanPermission() {
        log.info("正在读取所需要的controller:" + scanControllerPackage.getPackages());

        //遍历scanControllerPackage.getPackages()获取的所有controller集合，在一个集合里面
        //一个set集合分成多个set集合放在bigSet集合中
        Set<Class<?>> bigSet = new HashSet<>();
        for (String PackageName : scanControllerPackage.getPackages()) {
            Set<Class<?>> classesSet = Classutil.getClasses(PackageName);//把每一个包下面controller取出来放在Set里面
            bigSet.addAll(classesSet);
        }

        //排除未添加@Controller注解或@RestController注解的类
        Set<Class<?>> controllerSet = bigSet.stream().filter(ann -> {
            Controller controller = ann.getAnnotation(Controller.class);
            RestController restController = ann.getAnnotation(RestController.class);
            return controller != null || restController != null;
        }).collect(Collectors.toSet());

        log.info("已扫描到所有Controller...{}", controllerSet);


        List<Permission> permissions = new ArrayList<>();
        //3.循环所有的controller里面的所有方法：双重循环
        for (Class<?> controller : controllerSet) {
            //获取当前controller里面的所有方法
            Method[] declaredMethods = controller.getDeclaredMethods();
            for (Method method : declaredMethods) {
                //判断PreAuthorize.class自定义注解存不存在
                PreAuthorize preAuthorize = method.getAnnotation(PreAuthorize.class);
                if (preAuthorize == null){
                    //方法上面没有@PreAuthorize注解，就跳过
                    continue;
                }
                //方法上面有@PreAuthorize注解，那就获取它的属性值，插入一行数据到t_permission表
                permissions.add(new Permission(preAuthorize.name(),preAuthorize.sn()
                        ,preAuthorize.menu_id() == 0 ? null:preAuthorize.menu_id()
                        ,preAuthorize.parent_id() == 0 ? null: preAuthorize.parent_id()));
                log.info("已扫描到 {}", method);
            }

        }
        //4.批量保存：先根据sn查询权限，如果存在就修改，不存在就新增
        for (Permission permission : permissions) {
            Permission permissionSn = permissionMapper.findBySn(permission.getSn());
            if (permissionSn == null){
                //添加
                permission.setDescs(permission.getName());
                permissionMapper.add(permission);
            }else {
                //修改
                permissionSn.setName(permission.getName());
                permissionSn.setMenu_id(permission.getMenu_id());
                permissionSn.setDescs(permission.getName());
                permissionSn.setParent_id(permission.getParent_id());
                permissionMapper.update(permissionSn);
            }

        }
        log.info("正在插入权限表数据....{}", permissions);
    }

    /**
     * 查询权限列表的树形结构
     * @return
     */
    @Override
    public List<Permission> getTree() {

        List<Permission> permissionList = permissionMapper.findAll();

        //创建一个map，放入map中
        Map<Long,Permission> permissionMap = new HashMap<>();
        permissionList.forEach(permission -> permissionMap.put(permission.getId(),permission));

        //创建一个一级权限集合
        ArrayList<Permission> firstPermission = new ArrayList<>();

        for (Permission permission : permissionList) {
            if (permission.getParent_id() == null){
                //parent_id等于null  就是一级  添加到一级权限集合中
                firstPermission.add(permission);
            }else {
                //不是一级权限，则需要找到它的父亲，将它设置成它父亲的儿子
                Permission parent = permissionMap.get(permission.getParent_id());
                parent.getChildren().add(permission);
            }
        }
        return firstPermission;
    }

}
